make libcURL timeout only on connection failure - c++

I'm using some auto-update function in my program. In case of connection failure, I would like the program to keep trying up to 15 seconds, and then announce failure. In order to achieve that, I used the following curl_easy_setopt for cURL easy option:
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15);
But then I discovered that if the download takes more than 15 seconds, the timeout error is announced.
How can I restrict the 15 seconds only to the case of failure? I.e., if there's no connection for 15 seconds?
More information
The full option list I use is the following:
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //verify ssl peer
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //verify ssl hostname
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this); //pointer to the current class as it's a GUI program
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, CurlProgress_CallbackFunc_UpdateProgress);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20);
and the call to start is done through:
CURLcode res = curl_easy_perform(curl);
If you require more information, please let me know.
Thank you.

Instead of
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20);
use
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 15);
The first line is the timeout for the connection phase. After the connection is established the timeout becomes irrelevant, but the two following lines make sure that if the average speed in a 15 second time frame drops below 1 byte per second, then the operation is aborted.
Also worth noting that curl will not try to reestablish any connection if it is dropped, because a TCP connection can still be hold if the physical connection is (temporarly) lost up until one of the sides decides to timeout.

Related

What could be reason of getting SSL connect error while posting json request to https url from Windows PC?

I am using libcurl.dll version 7.72.0.0 in Visual Studio for a C++ application.
When I am posting a JSON request to an HTTPS url on one Windows 7 PC with Service Pack 1, the request is posted successfully. But on other PC with same OS as Windows 7 Service Pack 1, I am getting response code 35 from curl_easy_perform(): SSL connect error.
What could be the reason of the same C++ code working on one Windows 7 PC and getting an error on other Windows 7 PC? Both PCs are on the same network.
Following is the C++ code:
curl_easy_setopt(curl, CURLOPT_URL, Url.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header);
// send all data to this function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
// we pass our 'chunk' struct to the callback function
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&sResponse);
//some servers don't like requests that are made without a user-agent
// field, so we provide one
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
printf("\npostthisData=%s\n", postthis);
if (itsHTTPSRequest)
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
// if we don't provide POSTFIELDSIZE, libcurl will strlen() by
// itself
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis));
curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT, m_RWTimeOut );
curl_easy_setopt( curl, CURLOPT_LOW_SPEED_TIME, m_RWTimeOut);
curl_easy_setopt( curl, CURLOPT_LOW_SPEED_LIMIT, 30L);

c++ libcurl - use the response from previous curl as parameter to another curl

I am using C++ libcurl to POST data to a webservice and everything works fine. I would like to use the webservice response (Json) as parameter to a make another POST in another webservice. Can you guys help me? Thank you very much
//FIRST POST
curl_easy_setopt(curl, CURLOPT_URL, url1.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
std::unique_ptr<std::string> httpResponse1(new std::string());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpResponse1.get());
curl_easy_perform(curl);
//SECOND POST
curl_easy_setopt(curl, CURLOPT_URL, url2.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, httpResponse1);
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
std::unique_ptr<std::string> httpResponse2(new std::string());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpResponse2.get());
curl_easy_perform(curl);
I'd recommend reading and basing such work on the public libcurl examples that have what you need:
Receive in memory: getinmemory.c
POST from memory (and receive that response too in memory): postinmemory.c

curl ssh key C++ error "Username/PublicKey combination invalid"

I'm working on embedded system in C++.
I'm actualy try to connect my system on ssh to my computer host.
I use this code:
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_SFTP);
curl_easy_setopt(curl, CURLOPT_URL,
"sftp://10.0.0.100/");
/* Define our callback to get called when there's data to be written */
curl_easy_setopt(curl, CURLOPT_USERPWD, "root:password");
curl_easy_setopt(curl,CURLOPT_KEYPASSWD,"password");
curl_easy_setopt(curl, CURLOPT_PORT, 22);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, 1000);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, 10);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
/* Set a pointer to our struct to pass to the callback */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
curl_easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE,std::string(PublicKey).c_str());
curl_easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE,std::string(PrivateKey).c_str());
curl_easy_setopt(curl, CURLOPT_SSH_AUTH_TYPES,CURLSSH_AUTH_PUBLICKEY);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
but the result of my programme is:
Trying 10.0.0.100...
Connected to 10.0.0.100 (10.0.0.100) port 22 (#0)
SSH MD5 fingerprint: dfdaa04ed1f80caf1e588349846b7025
SSH authentication methods available: publickey,password
Using SSH public key file '/opt/appl/var/PublicKey'
Using SSH private key file '/opt/appl/var/PrivateKey'
SSH public key authentication failed: Username/PublicKey combination invalid
Authentication failure
Closing connection 0
Unfortunately i can't creat some ssh key on my system because it dosen't accept system() commandes so i directly import keys from another system.
Dose it the cause of my error?

c++ curl returns receive error when usng proxies

As the header says, I am trying to load a page with proxy using curl on c++.
I have tried the proxy with curl linux command and got a result without a password, on my code i do:
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_ENCODING, "");
curl_easy_setopt(curl, CURLOPT_AUTOREFERER, true);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlRead);
curl_easy_setopt(curl, CURLOPT_USERAGENT, agent);
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, 1L);
curl_easy_setopt(curl, CURLOPT_PROXY, "<proxy IP>:80");
res = curl_easy_perform(curl);
but res returns as 56 (CURLE_RECV_ERROR) and the manual says
Failure with receiving network data.
EDIT: I have tried another proxy (also working from terminal) and now I dont get a response at all, it simply stuck.

libcurl http post timeout

I am using curl version 7.15.5 in multi-thread environment. Each thread is initializing and freeing its own curl object. Below is the code, executed for each thread:
CURL* curl = curl_easy_init();
tRespBuffer respBuffer = {NULL, 0};
char errorBuf[CURL_ERROR_SIZE +1];
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: text/xml; charset=gbk");
headers = curl_slist_append(headers, "Expect:");
curl_easy_setopt(curl, CURLOPT_URL, url_);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,encr.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,strlen(encr.c_str()));
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpSmsServer::processHttpResponse);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&respBuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20); // wait for 20 seconds before aborting the transacttion
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuf); // error returned if any..
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); // No signals allowed in case of multithreaded apps
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
All the four threads are posting data to http server simultaneously. I see HTTP response timeout for some of the POST requests (~3% of requests). Any idea what could be the reason of timeouts ? I assume http server should not take more than 20 seconds to respond back.
CURLOPT_TIMEOUT includes all the time of http request, have you transferred huge data?
CURLOPT_TIMEOUT:Pass a long as parameter containing the maximum time in seconds that you allow the libcurl transfer operation to take. Normally, name lookups can take a considerable time and limiting operations to less than a few minutes risk aborting perfectly normal operations.