0

I'm learning how to use CURL properly, and according to all the examples (the documentation is a pain) my code should work, but for some reason sometimes it connects and other times it won't.

I did check if there was a firewall problem, or the antivirus interfering, but both are turn off and the problem persists.

The main idea is to connect to a local server (rpi), and in the future to an external server for backup/updates.

My code is as follows. Here's the callback function, and the actual function that does all the work, the different URLs are for example purposes.

static std::size_t callback(const char* in,std::size_t size, std::size_t num, std::string* out){
    Silo* silo = new Silo();    
    const std::size_t totalBytes(size * num);
    std::string data = std::to_string(totalBytes);
    silo->Log("Total Bytes recive " + QString::fromStdString(data));
    out->append(in, totalBytes);
    return totalBytes;
}  

void Server::RPI_Request(){
    Silo* silo = new Silo();
    //curl_global_init(CURL_GLOBAL_ALL);
    CURL *curl = curl_easy_init();
    
    const std::string url_A("http://date.jsontest.com/");
    const std::string url_B("https://jsonplaceholder.typicode.com/todos/1");
    const std::string url_C("https://www.google.com/");
    const std::string url_D("https://stackoverflow.com/");
    
    if (curl){
        CURLcode res;
       
        // set Ip Direction
        curl_easy_setopt(curl, CURLOPT_URL, url_C.c_str() );
        // Don't bother trying IPv6, which would increase DNS resolution time.
        curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

        // Don't wait forever, time out after 10 seconds.
        silo->Log("antes de timeout");
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
 
        // Follow HTTP redirects if necessary.
        //curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

        // Response information.
        long httpCode(0);
        std::unique_ptr<std::string> httpData(new std::string());
        
        // Hook up data handling function.
        silo->Log("antes de write function");
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
        
        // Hook up data container (will be passed as the last parameter to the
        // callback handling function).  Can be any pointer type, since it will
        // internally be passed as a void pointer.
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());

        // Run our HTTP GET command, capture the HTTP response code, and clean up.
        silo->Log("antes de easy perform");
        res = curl_easy_perform(curl);
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
        
        silo->Log("Respuesta de httpCode: " + QString::number(httpCode));
        if (res != CURLE_OK){
          silo->Log("Hay pedo no se conecto " + QString::fromStdString(url_C) );
          
        } else {
          silo->Log("Coneccion establecida con " + QString::fromStdString(url_C));   
          
        }
     
        curl_easy_cleanup(curl);
        //curl_global_cleanup();
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
lightshadown
  • 165
  • 1
  • 1
  • 10
  • 4
    Unrelated: You seem to be leaking a lot of these `Silo` things. I recommend reading a bit more into the usages of `new`. I recommend starting with [Why should C++ programmers minimize use of 'new'?](https://stackoverflow.com/questions/6500313/why-should-c-programmers-minimize-use-of-new) – user4581301 Sep 22 '21 at 22:04
  • 2
    Likewise unrelated, from what I see, there is also no reason for `httpData` to be a dynamic managed (via smart pointer or otherwise). `std::string httpData;` and then using `curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpData);` would work. This code is a synchronous call. `httpData` exists for the lifetime of said-call. More code != more better. – WhozCraig Sep 22 '21 at 22:08
  • `CURLOPT_TIMEOUT` requires `long`, you pass `int`. – 273K Sep 22 '21 at 22:21
  • What are the errors when it does not work? – Martin York Sep 22 '21 at 22:42
  • What value does `res` hold when `curl_easy_perform()` fails to connect? You can't retrieve `CURLINFO_RESPONSE_CODE` if `res` is not `CURLE_OK`. Also, have a look at [`CURLOPT_CONNECTTIMEOUT`](https://curl.se/libcurl/c/CURLOPT_CONNECTTIMEOUT.html). – Remy Lebeau Sep 22 '21 at 23:21
  • @user4581301 the use of that pointer is for my log function, honestly its the only way i manage to make it work, dont know a better use. S.M. not sure about that i did copy it from an example and forgot to check the documentation from that one, and is a pain the oficial docs. Martin York, the program runs but i never connects – lightshadown Sep 23 '21 at 01:22
  • @RemyLebeau the response is 0, but i added **std::string error = curl_easy_strerror(res);** and the response is **SSL peer certificate or SSH remote key was not OK** – lightshadown Sep 23 '21 at 01:28
  • @lightshadown You can't get that error message string if you pass `CURLE_OK` (0) to `curl_easy_strerror()`. Are you sure `curl_easy_perform()` is not returning something more like `CURLE_SSL_CONNECT_ERROR` (35) or `CURLE_SSL_CERTPROBLEM` (58) instead? As for what WhozCraig described, you can use `std::string httpData; curl_easy_setopt(curl, CURLOPT_WRITEDATA, &httpData);` instead, no `new` needed. – Remy Lebeau Sep 23 '21 at 02:15
  • @RemyLebeau, you were right now i got the culprit using **curl_easy_strerror(res)**, i got **CURLE_PEER_FAILED_VERIFICATION,** /* 60 not sure why i got that, even when i use the simplest code i can from curl, i left only the init and cleanup and i got the same issue – lightshadown Sep 23 '21 at 16:15
  • @lightshadown OK, so there is a problem with the server's certificate. Not much you can do about that on the client side, unless you validate the certificate manually via [`CURLOPT_SSL_CTX_FUNCTION`](https://curl.se/libcurl/c/CURLOPT_SSL_CTX_FUNCTION.html), or disable validation via [`CURLOPT_SSL_VERIFYPEER`](https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html), for instance. – Remy Lebeau Sep 23 '21 at 16:39
  • @RemyLebeau, if thats the case im going to check the documentation for local server, i need to conect to my RPi server locally, i just wanted to connect for updates on the future (Heroku/github) – lightshadown Sep 23 '21 at 22:41
  • this might sound crazy but i just change the page to a normal/non https page and it worked, meabe the problem was i was trying to stablish a non secure connection a secure page, and my http code now its 200, so it make the conecction. – lightshadown Sep 24 '21 at 03:07

0 Answers0