72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering This file is part of systemd.
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering Copyright 2014 Lennart 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 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 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 Poetteringstatic void curl_glue_check_finished(CurlGlue *g) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering g->on_finished(g, msg->easy_handle, msg->data.result);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT))
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_socket_action(g->curl, translated_fd, action, &k) < 0) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering log_debug("Failed to propagate IO event.");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_set_enabled(io, SD_EVENT_OFF);
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_io_events(io, events) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
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 if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering sd_event_source_set_description(io, "curl-io");
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering r = hashmap_put(g->ios, FD_TO_PTR(s), io);
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstatic int curl_glue_on_timer(sd_event_source *s, uint64_t usec, void *userdata) {
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 Poetteringstatic int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_time(g->timer, usec) < 0)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0)
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 sd_event_source_set_description(g->timer, "curl-timer");
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while ((io = hashmap_steal_first(g->ios))) {
23e096cc60eb73f24b812e4ceba7c4c2c141e2dbLennart Poettering hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_glue_new(CurlGlue **glue, sd_event *event) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering _cleanup_(curl_glue_unrefp) CurlGlue *g = NULL;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETDATA, g) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_SOCKETFUNCTION, curl_glue_socket_callback) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_TIMERDATA, g) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_setopt(g->curl, CURLMOPT_TIMERFUNCTION, curl_glue_timer_callback) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_glue_make(CURL **ret, const char *url, void *userdata) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* curl_easy_setopt(c, CURLOPT_VERBOSE, 1L); */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_URL, url) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_PRIVATE, userdata) != CURLE_OK) {
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering useragent = strjoina(program_invocation_short_name, "/" PACKAGE_VERSION);
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_USERAGENT, useragent) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_easy_setopt(c, CURLOPT_FOLLOWLOCATION, 1L) != CURLE_OK) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering if (curl_multi_add_handle(g->curl, c) != CURLM_OK)
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringvoid curl_glue_remove_and_free(CurlGlue *g, CURL *c) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringstruct curl_slist *curl_slist_new(const char *first, ...) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *i;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poetteringint curl_header_strdup(const void *contents, size_t sz, const char *field, char **value) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering const char *p = contents;
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Skip over preceeding whitespace */
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while (sz > 0 && strchr(WHITESPACE, p[0])) {
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering /* Truncate trailing whitespace*/
72648326ea6d3e68cdb0b5890df737047d031a41Lennart Poettering while (sz > 0 && strchr(WHITESPACE, p[sz-1]))
5fa89b2cb366d533e56a9b7a9ce548480776f973Lennart Poetteringint curl_parse_http_time(const char *t, usec_t *ret) {
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez const char *e;
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez loc = newlocale(LC_TIME_MASK, "C", (locale_t) 0);
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 e = strptime_l(t, "%A, %d-%b-%y %H:%M:%S %Z", &tm, loc);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez if (!e || *e != 0)
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez e = strptime_l(t, "%a %b %d %H:%M:%S %Y", &tm, loc);
0193ad26ba121f3df259cc8b3bab54a99b8e5252Cristian Rodríguez if (!e || *e != 0)