Skip to content
Snippets Groups Projects
casupcurl.cpp 2.96 KiB
Newer Older
Giacomo Strangolino's avatar
Giacomo Strangolino committed
#include "casupcurl.h"
#include "casupjsoniz.h"
#include <curl/curl.h>
#include <cumacros.h>

class CaSupCurlPrivate {
public:
    CURL *curl;
    std::string url, message, response;
    bool ok, ssl_verify_peer;
};

CaSupCurl::CaSupCurl(const std::string& url, bool ssl_verifypeer) {
    d = new CaSupCurlPrivate;
    d->url = url + "/bu/src-bundle";
    d->ssl_verify_peer = ssl_verifypeer;
    d->curl = curl_easy_init();
    d->ok = d->curl != nullptr;
}

CaSupCurl::~CaSupCurl() {
    curl_easy_cleanup(d->curl);
    delete d;
}

std::map<std::string, std::string> CaSupCurl::xmit(const std::map<std::string,std::string> &datamap) {
    std::map<std::string, std::string> resultmap;
    int cnt = 0;
    bool ok;
    std::string message;
    CaSupJsoniz jiz;
    for(const auto& [chan, json] : datamap) {
        ++cnt;
        struct curl_slist *slist = nullptr;
        std::string chanhdr = "X-Channel: " + chan;
        std::string content_len = "Content-Length: " + std::to_string(json.length());
        char errbuf[CURL_ERROR_SIZE];
        curl_slist_append(slist, "Accept: application/json");
        curl_slist_append(slist, "Content-Type: application/json");
        curl_slist_append(slist, chanhdr.c_str());
        curl_slist_append(slist, content_len.c_str());
        curl_easy_setopt(d->curl, CURLOPT_URL, d->url.c_str());
        curl_easy_setopt(d->curl, CURLOPT_HEADER, slist);
        curl_easy_setopt(d->curl, CURLOPT_POSTFIELDS, json.c_str());
        curl_easy_setopt(d->curl, CURLOPT_ERRORBUFFER, errbuf);
        // CURLOPT_SSL_VERIFYPEER true by default in CaOptParser
        curl_easy_setopt(d->curl, CURLOPT_SSL_VERIFYPEER, d->ssl_verify_peer);
        // suppress response to stdout
        curl_easy_setopt(d->curl, CURLOPT_WRITEFUNCTION, CaSupCurl::write_callback);
        CaSupCurlWriteFuncData *wd = new CaSupCurlWriteFuncData(std::to_string(cnt));
        d->response.clear();
        curl_easy_setopt(d->curl, CURLOPT_WRITEDATA, (void *) &d->response );

        CURLcode cuco = curl_easy_perform(d->curl);
        ok = (cuco == CURLE_OK);
        // if CURL successful let message hold the server reply
        ok ?  message = d->response :
                message = jiz.make_err_msg(std::string("CaSupCurl::xmit: ")  + curl_easy_strerror(cuco) + ": "
                                           + errbuf + ": code " + std::to_string(cuco));
        curl_slist_free_all(slist);
        resultmap[chan] = message;
        delete wd;
    }
    return resultmap;
}

size_t CaSupCurl::write_callback(char *contents, size_t size, size_t nmemb, void *userdata) {
    std::string *response = static_cast<std::string *>(userdata);
    response->append((char*)contents, size * nmemb);
    return size * nmemb;
}

int CaSupCurl::socket_callback(CURL *easy, curl_socket_t s, int what, void *userp, void *socketp) {
    return 0;
}

int CaSupCurl::start_timeout(CURLM *multi, long timeout_ms, void *userp) {
    return 0;
}

const std::string &CaSupCurl::response() const {
    return d->response;
}