72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering/***
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering This file is part of systemd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Copyright 2014 Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is free software; you can redistribute it and/or modify it
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering under the terms of the GNU Lesser General Public License as published by
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering (at your option) any later version.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering systemd is distributed in the hope that it will be useful, but
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Lesser General Public License for more details.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering You should have received a copy of the GNU Lesser General Public License
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering***/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering#include "curl-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "string-util.h"
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic void curl_glue_check_finished(CurlGlue *g) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering CURLMsg *msg;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int k = 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering msg = curl_multi_info_read(g->curl, &k);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!msg)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (msg->msg != CURLMSG_DONE)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (g->on_finished)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering g->on_finished(g, msg->easy_handle, msg->data.result);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering CurlGlue *g = userdata;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int action, k = 0, translated_fd;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(s);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering action = CURL_POLL_INOUT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (revents & EPOLLIN)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering action = CURL_POLL_IN;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (revents & EPOLLOUT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering action = CURL_POLL_OUT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering action = 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_socket_action(g->curl, translated_fd, action, &k) < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Failed to propagate IO event.");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_glue_check_finished(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source *io;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering CurlGlue *g = userdata;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering uint32_t events = 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(curl);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering io = hashmap_get(g->ios, FD_TO_PTR(s));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (action == CURL_POLL_REMOVE) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (io) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int fd;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fd = sd_event_source_get_io_fd(io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(fd >= 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_set_enabled(io, SD_EVENT_OFF);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_unref(io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering hashmap_remove(g->ios, FD_TO_PTR(s));
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering safe_close(fd);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (action == CURL_POLL_IN)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering events = EPOLLIN;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (action == CURL_POLL_OUT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering events = EPOLLOUT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else if (action == CURL_POLL_INOUT)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering events = EPOLLIN|EPOLLOUT;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (io) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_io_events(io, events) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering } else {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_close_ int fd = -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* When curl needs to remove an fd from us it closes
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * the fd first, and only then calls into us. This is
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * nasty, since we cannot pass the fd on to epoll()
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * anymore. Hence, duplicate the fds here, and keep a
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering * copy for epoll which we control after use. */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fd = fcntl(s, F_DUPFD_CLOEXEC, 3);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (fd < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_set_description(io, "curl-io");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering r = hashmap_put(g->ios, FD_TO_PTR(s), io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_oom();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_unref(io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_oom();
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering hashmap_remove(g->ios, FD_TO_PTR(s));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_unref(io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fd = -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_on_timer(sd_event_source *s, uint64_t usec, void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering CurlGlue *g = userdata;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int k = 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(s);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_socket_action(g->curl, CURL_SOCKET_TIMEOUT, 0, &k) != CURLM_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Failed to propagate timeout.");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_glue_check_finished(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering CurlGlue *g = userdata;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering usec_t usec;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(curl);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (timeout_ms < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (g->timer) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (g->timer) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_time(g->timer, usec) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering } else {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_set_description(g->timer, "curl-timer");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart PoetteringCurlGlue *curl_glue_unref(CurlGlue *g) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source *io;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!g)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (g->curl)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_multi_cleanup(g->curl);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((io = hashmap_steal_first(g->ios))) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int fd;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering fd = sd_event_source_get_io_fd(io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(fd >= 0);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering safe_close(fd);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_unref(io);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering hashmap_free(g->ios);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_unref(g->timer);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_unref(g->event);
c5285fbfcede2e0f54d2b5f14193041067cd2af6David Herrmann free(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_glue_new(CurlGlue **glue, sd_event *event) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering g = new0(CurlGlue, 1);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!g)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOMEM;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (event)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering g->event = sd_event_ref(event);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering else {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = sd_event_default(&g->event);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (r < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering g->curl = curl_multi_init();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!g->curl)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOMEM;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETDATA, g) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETFUNCTION, curl_glue_socket_callback) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_TIMERDATA, g) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EINVAL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *glue = g;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering g = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_glue_make(CURL **ret, const char *url, void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *useragent;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering CURL *c;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering int r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(ret);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(url);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering c = curl_easy_init();
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!c)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOMEM;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_URL, url) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = -EIO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering goto fail;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_PRIVATE, userdata) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = -EIO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering goto fail;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering useragent = strjoina(program_invocation_short_name, "/" PACKAGE_VERSION);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_USERAGENT, useragent) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = -EIO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering goto fail;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = -EIO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering goto fail;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *ret = c;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringfail:
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_easy_cleanup(c);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return r;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_glue_add(CurlGlue *g, CURL *c) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(c);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_add_handle(g->curl, c) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -EIO;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringvoid curl_glue_remove_and_free(CurlGlue *g, CURL *c) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering assert(g);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!c)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (g->curl)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_multi_remove_handle(g->curl, c);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_easy_cleanup(c);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstruct curl_slist *curl_slist_new(const char *first, ...) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct curl_slist *l;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering va_list ap;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!first)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering l = curl_slist_append(NULL, first);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!l)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering va_start(ap, first);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering for (;;) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering struct curl_slist *n;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *i;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering i = va_arg(ap, const char*);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!i)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering break;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering n = curl_slist_append(l, i);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!n) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering va_end(ap);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering curl_slist_free_all(l);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering l = n;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering va_end(ap);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return l;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_header_strdup(const void *contents, size_t sz, const char *field, char **value) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *p = contents;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering size_t l;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering char *s;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering l = strlen(field);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sz < l)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (memcmp(p, field, l) != 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering p += l;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sz -= l;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (memchr(p, 0, sz))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 0;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Skip over preceeding whitespace */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while (sz > 0 && strchr(WHITESPACE, p[0])) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering p++;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sz--;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering }
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Truncate trailing whitespace*/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while (sz > 0 && strchr(WHITESPACE, p[sz-1]))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sz--;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering s = strndup(p, sz);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (!s)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return -ENOMEM;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering *value = s;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering return 1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering}
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poetteringint curl_parse_http_time(const char *t, usec_t *ret) {
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez const char *e;
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez locale_t loc;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering struct tm tm;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering time_t v;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering assert(t);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering assert(ret);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez loc = newlocale(LC_TIME_MASK, "C", (locale_t) 0);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez if (loc == (locale_t) 0)
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez return -errno;
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez /* RFC822 */
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez e = strptime_l(t, "%a, %d %b %Y %H:%M:%S %Z", &tm, loc);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez if (!e || *e != 0)
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez /* RFC 850 */
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez e = strptime_l(t, "%A, %d-%b-%y %H:%M:%S %Z", &tm, loc);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez if (!e || *e != 0)
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez /* ANSI C */
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez e = strptime_l(t, "%a %b %d %H:%M:%S %Y", &tm, loc);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez freelocale(loc);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez if (!e || *e != 0)
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez return -EINVAL;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez v = timegm(&tm);
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering if (v == (time_t) -1)
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return -EINVAL;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poettering *ret = (usec_t) v * USEC_PER_SEC;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering return 0;
901992209e3c87a4cf06b530d7b26ae2d35680efLennart Poettering}