Exemplo n.º 1
0
static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
        CurlGlue *g = userdata;
        int action, k = 0, translated_fd;

        assert(s);
        assert(g);

        translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));

        if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT))
                action = CURL_POLL_INOUT;
        else if (revents & EPOLLIN)
                action = CURL_POLL_IN;
        else if (revents & EPOLLOUT)
                action = CURL_POLL_OUT;
        else
                action = 0;

        if (curl_multi_socket_action(g->curl, translated_fd, action, &k) < 0) {
                log_debug("Failed to propagate IO event.");
                return -EINVAL;
        }

        curl_glue_check_finished(g);
        return 0;
}
Exemplo n.º 2
0
CurlGlue *curl_glue_unref(CurlGlue *g) {
        sd_event_source *io;

        if (!g)
                return NULL;

        if (g->curl)
                curl_multi_cleanup(g->curl);

        while ((io = hashmap_steal_first(g->ios))) {
                int fd;

                fd = sd_event_source_get_io_fd(io);
                assert(fd >= 0);

                hashmap_remove(g->translate_fds, FD_TO_PTR(fd));

                safe_close(fd);
                sd_event_source_unref(io);
        }

        hashmap_free(g->ios);

        sd_event_source_unref(g->timer);
        sd_event_unref(g->event);
        free(g);

        return NULL;
}
Exemplo n.º 3
0
int asynchronous_close(int fd) {
        int r;

        /* This is supposed to behave similar to safe_close(), but
         * actually invoke close() asynchronously, so that it will
         * never block. Ideally the kernel would have an API for this,
         * but it doesn't, so we work around it, and hide this as a
         * far away as we can. */

        if (fd >= 0) {
                PROTECT_ERRNO;

                r = asynchronous_job(close_thread, FD_TO_PTR(fd));
                if (r < 0)
                         assert_se(close_nointr(fd) != -EBADF);
        }

        return -1;
}
Exemplo n.º 4
0
int fdset_remove(FDSet *s, int fd) {
        assert(s);
        assert(fd >= 0);

        return set_remove(MAKE_SET(s), FD_TO_PTR(fd)) ? fd : -ENOENT;
}
Exemplo n.º 5
0
bool fdset_contains(FDSet *s, int fd) {
        assert(s);
        assert(fd >= 0);

        return !!set_get(MAKE_SET(s), FD_TO_PTR(fd));
}
Exemplo n.º 6
0
int fdset_put(FDSet *s, int fd) {
        assert(s);
        assert(fd >= 0);

        return set_put(MAKE_SET(s), FD_TO_PTR(fd));
}
Exemplo n.º 7
0
static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
        sd_event_source *io;
        CurlGlue *g = userdata;
        uint32_t events = 0;
        int r;

        assert(curl);
        assert(g);

        io = hashmap_get(g->ios, FD_TO_PTR(s));

        if (action == CURL_POLL_REMOVE) {
                if (io) {
                        int fd;

                        fd = sd_event_source_get_io_fd(io);
                        assert(fd >= 0);

                        sd_event_source_set_enabled(io, SD_EVENT_OFF);
                        sd_event_source_unref(io);

                        hashmap_remove(g->ios, FD_TO_PTR(s));
                        hashmap_remove(g->translate_fds, FD_TO_PTR(fd));

                        safe_close(fd);
                }

                return 0;
        }

        r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops);
        if (r < 0) {
                log_oom();
                return -1;
        }

        r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops);
        if (r < 0) {
                log_oom();
                return -1;
        }

        if (action == CURL_POLL_IN)
                events = EPOLLIN;
        else if (action == CURL_POLL_OUT)
                events = EPOLLOUT;
        else if (action == CURL_POLL_INOUT)
                events = EPOLLIN|EPOLLOUT;

        if (io) {
                if (sd_event_source_set_io_events(io, events) < 0)
                        return -1;

                if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
                        return -1;
        } else {
                _cleanup_close_ int fd = -1;

                /* When curl needs to remove an fd from us it closes
                 * the fd first, and only then calls into us. This is
                 * nasty, since we cannot pass the fd on to epoll()
                 * anymore. Hence, duplicate the fds here, and keep a
                 * copy for epoll which we control after use. */

                fd = fcntl(s, F_DUPFD_CLOEXEC, 3);
                if (fd < 0)
                        return -1;

                if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
                        return -1;

                (void) sd_event_source_set_description(io, "curl-io");

                r = hashmap_put(g->ios, FD_TO_PTR(s), io);
                if (r < 0) {
                        log_oom();
                        sd_event_source_unref(io);
                        return -1;
                }

                r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
                if (r < 0) {
                        log_oom();
                        hashmap_remove(g->ios, FD_TO_PTR(s));
                        sd_event_source_unref(io);
                        return -1;
                }

                fd = -1;
        }

        return 0;
}