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