tev_curl.c revision ca90f2102a43a3d49a2ef26610d7b4ff3062a823
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/*
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek SSSD
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek libcurl tevent integration
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek Copyright (C) Red Hat, 2016
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek This program is free software; you can redistribute it and/or modify
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek it under the terms of the GNU General Public License as published by
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek the Free Software Foundation; either version 3 of the License, or
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek (at your option) any later version.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek This program is distributed in the hope that it will be useful,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek GNU General Public License for more details.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek You should have received a copy of the GNU General Public License
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek*/
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <stdio.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <string.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <stdlib.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <sys/time.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <unistd.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <errno.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <talloc.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <tevent.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include <curl/curl.h>
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include "util/util.h"
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#include "util/tev_curl.h"
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#define IOBUF_CHUNK 1024
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek#define IOBUF_MAX 4096
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic bool global_is_curl_initialized;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief The main structure of the tcurl module.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Use tcurl_init() to initialize it, then pass to the request.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Should be kept opaque in the future.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @see tcurl_init()
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_ctx {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_context *ev;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* See where we set CURLMOPT_TIMERFUNCTION */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_timer *process_timer;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Since we want the API to be non-blocking, all the transfers use
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the curl's multi interface:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * https://ec.haxx.se/libcurl-drive-multi.html
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * and then each transfer also uses an easy interface instance for
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the transfer's private data
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLM *multi_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek};
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief A tevent wrapper around curl socket
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_sock {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx; /* Backchannel to the main context */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_socket_t sockfd; /* curl socket is an int typedef on Unix */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_fd *fde; /* tevent tracker of the fd events */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek};
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief A state of one curl transfer
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Intentionally breaking the tevent coding style here and making the struct available
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * in the whole module so that the structure is available to curl callbacks that
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * need to access the state of the transfer.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @see handle_curlmsg_done()
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_http_state {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Input parameters */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *socket_path;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *url;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int timeout;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct sss_iobuf *inbuf;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Internal state */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURL *http_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct curl_slist *curl_headers;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Output data */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct sss_iobuf *outbuf;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek long http_code;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek};
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t curl_code2errno(CURLcode crv)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "curl error %d: %s\n", crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (crv) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* HTTP error does not fail the whole request, just returns the error
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * separately
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_HTTP_RETURNED_ERROR:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_OK:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_URL_MALFORMAT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EBADMSG;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_COULDNT_CONNECT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EHOSTUNREACH;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_REMOTE_ACCESS_DENIED:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EACCES;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_OUT_OF_MEMORY:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLE_OPERATION_TIMEDOUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ETIMEDOUT;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_global_init(void)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (global_is_curl_initialized == false) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = curl_global_init(CURL_GLOBAL_ALL);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot initialize global curl options [%d]\n", ret);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek global_is_curl_initialized = true;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic const char *http_req2str(enum tcurl_http_request req)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (req) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_GET:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return "GET";
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_PUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return "PUT";
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_DELETE:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return "DELETE";
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return "Uknown request type";
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int curl2tev_flags(int curlflags)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int flags = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (curlflags) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_IN:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags |= TEVENT_FD_READ;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_OUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags |= TEVENT_FD_WRITE;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_INOUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags |= (TEVENT_FD_READ | TEVENT_FD_WRITE);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return flags;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void handle_curlmsg_done(CURLMsg *message)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURL *easy_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLcode crv;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek char *done_url;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_http_state *state;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek easy_handle = message->easy_handle;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (easy_handle == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "BUG: NULL handle for message %p\n", message);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (DEBUG_IS_SET(SSSDBG_TRACE_FUNC)) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_getinfo(easy_handle, CURLINFO_EFFECTIVE_URL, &done_url);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_MINOR_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot get CURLINFO_EFFECTIVE_URL [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* not fatal since we need this only for debugging */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek } else {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, "Handled %s\n", done_url);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, (void *) &req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot get CURLINFO_PRIVATE [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state = tevent_req_data(req, struct tcurl_http_state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "BUG: request has no state\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_req_error(req, EFAULT);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = curl_code2errno(message->data.result);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "curl operation failed [%d]: %s\n", ret, sss_strerror(ret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_req_error(req, ret);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* If there was no fatal error, let's read the HTTP error code and mark
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the request as done
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &state->http_code);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, "Cannot get HTTP status code\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_req_error(req, EFAULT);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_req_done(req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void process_curl_activity(struct tcurl_ctx *tctx)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMsg *message;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int pending;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek while ((message = curl_multi_info_read(tctx->multi_handle, &pending))) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (message->msg) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURLMSG_DONE:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek handle_curlmsg_done(message);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "noop for curl msg %d\n", message->msg);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void tcurlsock_input_available(struct tevent_context *ev,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_fd *fde,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek uint16_t flags,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *data)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_sock *tcs = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int curl_flags = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int running_handles;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs = talloc_get_type(data, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcs == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (flags & TEVENT_FD_READ) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_flags |= CURL_CSELECT_IN;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (flags & TEVENT_FD_WRITE) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_flags |= CURL_CSELECT_OUT;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* multi_socket_action might invalidate tcs when the transfer ends,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * so we need to store tctx separately
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx = tcs->tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* https://ec.haxx.se/libcurl-drive-multi-socket.html */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_socket_action(tcs->tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->sockfd,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_flags,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek &running_handles);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek process_curl_activity(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/**
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * @brief Registers a curl's socket with tevent
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * Creates a private structure, registers the socket with tevent and finally
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * registers the tcurl_sock structure as a private pointer for the curl
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * socket for later
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic struct tcurl_sock *register_curl_socket(struct tcurl_ctx *tctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_socket_t sockfd,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int flags)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_sock *tcs;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs = talloc_zero(tctx, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcs == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->sockfd = sockfd;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->tctx = tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcs->fde = tevent_add_fd(tctx->ev, tcs, sockfd, flags,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcurlsock_input_available, tcs);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcs->fde == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_free(tcs);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_assign(tctx->multi_handle, sockfd, (void *) tcs);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return tcs;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek/* libcurl informs the application about socket activity to wait for with
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * this callback */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int handle_socket(CURL *easy,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_socket_t s,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int action,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userp,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *socketp)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_sock *tcsock;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int flags = 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx = talloc_get_type(userp, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Activity on curl socket %d socket data %p\n", s, socketp);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (action) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_IN:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_OUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_INOUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* There is some activity on a socket */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek flags = curl2tev_flags(action);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (socketp == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* If this socket doesn't have private data, it must be a new one,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * let's start tracking it with tevent
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcsock = register_curl_socket(tctx, s, flags);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcsock == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek } else {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* If we are already tracking this socket, just set the correct
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * flags for tevent and pass the control to tevent
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcsock = talloc_get_type(socketp, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcsock == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "BUG: No private data for socket %d\n", s);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_fd_set_flags(tcsock->fde, flags);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case CURL_POLL_REMOVE:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* This socket is being closed by curl, so we need to.. */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcsock = talloc_get_type(socketp, struct tcurl_sock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tcsock == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "BUG: Trying to remove an untracked socket %d\n", s);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* ..stop tracking the socket with the multi handle.. */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_assign(tctx->multi_handle, s, NULL);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* ..and stop tracking the fd with tevent */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_free(tcsock);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void check_curl_timeouts(struct tcurl_ctx *tctx)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int running_handles;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_socket_action(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURL_SOCKET_TIMEOUT,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek 0,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek &running_handles);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_ALL,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Still tracking %d outstanding requests\n", running_handles);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* https://ec.haxx.se/libcurl-drive-multi-socket.html */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek process_curl_activity(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic void check_fd_activity(struct tevent_context *ev,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_timer *te,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct timeval current_time,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *private_data)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = talloc_get_type(private_data, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek check_curl_timeouts(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int schedule_fd_processing(CURLM *multi,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek long timeout_ms,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userp)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct timeval tv = { 0, 0 };
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = talloc_get_type(userp, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "timeout_ms: %ld\n", timeout_ms);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (timeout_ms == -1) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* man curlmopt_timerfunction(3) says:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * A timeout_ms value of -1 means you should delete your timer.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_zfree(tctx->process_timer);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek check_curl_timeouts(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tv = tevent_timeval_current_ofs(0, timeout_ms * 1000);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* There is only one timer per multi handle, so it makes sense to cancel
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * the previous one.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * From https://ec.haxx.se/libcurl-drive-multi-socket.html:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * There is only one timeout for the application to handle for the
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * entire multi handle, no matter how many individual easy handles
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * that have been added or transfers that are in progress. The timer
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * callback will be updated with the current nearest-in-time period to
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * wait.
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_zfree(tctx->process_timer);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx->process_timer = tevent_add_timer(tctx->ev, tctx, tv,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek check_fd_activity, tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx->process_timer == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return -1;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int tcurl_ctx_destroy(struct tcurl_ctx *ctx)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ctx == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_cleanup(ctx->multi_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tcurl_ctx *tcurl_init(TALLOC_CTX *mem_ctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_context *ev)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx = NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMcode cmret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Per the manpage it is safe to call the initialization multiple
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * times, as long as this is done before any other curl calls to
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * make sure we don't mangle the global curl environment
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_global_init();
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx = talloc_zero(mem_ctx, struct tcurl_ctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx->ev = ev;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tctx->multi_handle = curl_multi_init();
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (tctx->multi_handle == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_set_destructor(tctx, tcurl_ctx_destroy);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMOPT_SOCKETDATA, tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_SOCKETDATA [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /*
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * When there is some activity on a socket associated with the multi
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * handle, then the handle_socket() function will be called with the
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * global context as private data
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMOPT_SOCKETFUNCTION, handle_socket);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_SOCKETFUNCTION [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* When integrated in a mainloop, the curl multi interface must
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * kick off the communication in another eventloop tick. Similar
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * to the handle_socet function, the tcurl context is passed in
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * as private data
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLMOPT_TIMERFUNCTION, schedule_fd_processing);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_TIMERFUNCTION [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret = curl_multi_setopt(tctx->multi_handle, CURLMOPT_TIMERDATA, tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (cmret != CURLM_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Cannot set CURLMOPT_TIMERDATA [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek cmret, curl_multi_strerror(cmret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekfail:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_free(tctx);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_add_headers(struct tcurl_http_state *state,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *headers[]);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_set_options(struct tcurl_http_state *state,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek enum tcurl_http_request req_type);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int tcurl_http_cleanup_handle(TALLOC_CTX *ptr);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic size_t tcurl_http_write_data(char *ptr,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t size,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t nmemb,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userdata);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic size_t tcurl_http_read_data(void *ptr,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t size,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t nmemb,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userdata);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstruct tevent_req *tcurl_http_send(TALLOC_CTX *mem_ctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_context *ev,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_ctx *tctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek enum tcurl_http_request req_type,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *socket_path,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *url,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *headers[],
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct sss_iobuf *req_data,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int timeout)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_http_state *state;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek req = tevent_req_create(mem_ctx, &state, struct tcurl_http_state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (req == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return NULL;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->tctx = tctx;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->socket_path = socket_path;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->url = url;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->inbuf = req_data;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->timeout = timeout;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->outbuf = sss_iobuf_init_empty(state, IOBUF_CHUNK, IOBUF_MAX);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state->outbuf == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "HTTP request %s for URL %s\n", http_req2str(req_type), url);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek talloc_set_destructor((TALLOC_CTX *) state, tcurl_http_cleanup_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* All transfer share the same multi handle, but each trasfer has its own
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * easy handle we can use to set per-transfer options
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->http_handle = curl_easy_init();
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state->http_handle == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "curl_easy_init failed\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_add_headers(state, headers);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set CURL headers [%d]: %s\n", ret, sss_strerror(ret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_set_options(state, req, req_type);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set CURL options [%d]: %s\n", ret, sss_strerror(ret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek goto fail;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Pass control to the curl handling which will mark the request as
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * done
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_add_handle(tctx->multi_handle, state->http_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekfail:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_req_error(req, ret);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tevent_req_post(req, ev);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return req;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic int tcurl_http_cleanup_handle(TALLOC_CTX *ptr)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_http_state *state = talloc_get_type(ptr, struct tcurl_http_state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* it is safe to pass NULL here */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_multi_remove_handle(state->tctx->multi_handle, state->http_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_slist_free_all(state->curl_headers);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek curl_easy_cleanup(state->http_handle);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_add_headers(struct tcurl_http_state *state,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek const char *headers[])
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (headers == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* The headers will be freed later in tcurl_http_cleanup_handle */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek for (int i = 0; headers[i] != NULL; i++) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->curl_headers = curl_slist_append(state->curl_headers, headers[i]);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state->curl_headers == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add header %s\n", headers[i]);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Add a dummy header to suppress libcurl adding Expect 100-continue which
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * was causing libcurl to always wait for the internal timeout when sending
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek * a PUT/PATCH request
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->curl_headers = curl_slist_append(state->curl_headers, "Expect:");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state->curl_headers == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Cannot add the dummy expect header\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ENOMEM;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_set_common_options(struct tcurl_http_state *state,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLcode crv;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_HTTPHEADER,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->curl_headers);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set HTTP headers [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_UNIX_SOCKET_PATH,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->socket_path);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set UNIX socket path %s [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->socket_path, crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle, CURLOPT_URL, state->url);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set URL %s [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->url, crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle, CURLOPT_PRIVATE, req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set private data [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (state->timeout > 0) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_TIMEOUT,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->timeout);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set timeout [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_set_write_options(struct tcurl_http_state *state)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLcode crv;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_WRITEFUNCTION,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcurl_http_write_data);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set write function [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_WRITEDATA,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->outbuf);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set write data [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_set_read_options(struct tcurl_http_state *state)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLcode crv;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_READFUNCTION,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek tcurl_http_read_data);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set read function [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_READDATA,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek state->inbuf);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set read data [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic errno_t tcurl_set_options(struct tcurl_http_state *state,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek enum tcurl_http_request req_type)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLcode crv;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_set_common_options(state, req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_set_write_options(state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set write callbacks [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret, sss_strerror(ret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek switch (req_type) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_PUT:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* CURLOPT_UPLOAD enables HTTP_PUT */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_UPLOAD,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek 1L);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set the uplodad option [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* Causes libcurl to add a sane Content-Length header */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_INFILESIZE_LARGE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek (curl_off_t) sss_iobuf_get_size(state->inbuf));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set CURLOPT_INFILESIZE_LARGE [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = tcurl_set_read_options(state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set write callbacks [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret, sss_strerror(ret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_GET:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* GET just needs the write callbacks, nothing to do here.. */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek case TCURL_HTTP_DELETE:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv = curl_easy_setopt(state->http_handle,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek CURLOPT_CUSTOMREQUEST,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "DELETE");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (crv != CURLE_OK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to set the uplodad option [%d]: %s\n",
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek crv, curl_easy_strerror(crv));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EIO;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek break;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek default:
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EFAULT;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return EOK;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic size_t tcurl_http_write_data(char *ptr,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t size,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t nmemb,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userdata)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t realsize = size * nmemb;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct sss_iobuf *outbuf = talloc_get_type(userdata, struct sss_iobuf);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "---> begin libcurl data\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "%s\n", ptr);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "<--- end libcurl data\n");
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = sss_iobuf_write_len(outbuf, (uint8_t *) ptr, realsize);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek "Failed to write data to buffer [%d]: %s\n", ret, sss_strerror(ret));
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek /* zero signifies an EOF */
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return realsize;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekstatic size_t tcurl_http_read_data(void *ptr,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t size,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t nmemb,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek void *userdata)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek errno_t ret;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek size_t readbytes;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct sss_iobuf *inbuf = (struct sss_iobuf *) userdata;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (inbuf == NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return CURL_READFUNC_ABORT;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek ret = sss_iobuf_read(inbuf, size * nmemb, ptr, &readbytes);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (ret != EOK) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return CURL_READFUNC_ABORT;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return readbytes;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozekint tcurl_http_recv(TALLOC_CTX *mem_ctx,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tevent_req *req,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek int *_http_code,
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct sss_iobuf **_outbuf)
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek{
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek struct tcurl_http_state *state = tevent_req_data(req, struct tcurl_http_state);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek TEVENT_REQ_RETURN_ON_ERROR(req);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (_http_code != NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *_http_code = state->http_code;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek if (_outbuf != NULL) {
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek *_outbuf = talloc_steal(mem_ctx, state->outbuf);
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek }
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek return 0;
ca90f2102a43a3d49a2ef26610d7b4ff3062a823Jakub Hrozek}