Thank you Ray and Daniel for the quick response. Our application is
multithreaded and different threads will use it (Curl) for their own purposes
but the code here is isolated to a single thread (there is no sharing of curl
objects).
This is the code that is using curl:
CURL *curl_handle;
CURLcode curlcode;
const char *server_addr_str;
const char *proxy;
int proxyauth = CURLAUTH_NONE;
time_t send_ts = 0;
long cache_timeout_age = CURL_DEFAULT_DNS_CACHE_TIMEOUT;
long fresh_connect = CURL_DEFAULT_FRESH_CONNECT;
int iResult;
curl_handle = curl_easy_init();
if (!(curl_handle)) {
printf("%s(): curl_easy_init returned NULL",
__func__);
goto ERROUT;
}
// with libcurl, necessary to use http:// or https:// even
though the protocol is not http
snprintf(url, sizeof(url), "https://%s:%d", handle->server_name,
port);
curlcode = curl_easy_setopt(curl_handle, CURLOPT_URL, url);
if (curlcode != CURLE_OK) {
printf("%s(): curl_easy_setopt(CURLOPT_URL)
returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
if (proxy) {
curlcode = curl_easy_setopt(curl_handle,
CURLOPT_PROXY, proxy);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_PROXY) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
// if using an HTTP proxy, do a CONNECT
curlcode = curl_easy_setopt(curl_handle,
CURLOPT_HTTPPROXYTUNNEL, 1);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_HTTPPROXYTUNNEL) returned %d (%s)", __func__,
curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
if (proxyauth != CURLAUTH_NONE) {
curlcode =
curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, proxyauth);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_PROXYAUTH) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
}
send_ts = time(NULL);
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_PORT, port);
if (curlcode != CURLE_OK) {
printf("%s(): curl_easy_setopt(CURLOPT_PORT)
returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_CONNECT_ONLY,
1);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_CONNECT_ONLY) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_IPRESOLVE,
CURL_IPRESOLVE_V4); // XXX TODO a few changes needed for ipv6
if (curlcode != CURLE_OK) {
printf("%s(): curl_easy_setopt(CURLOPT_IPRESOLVE)
returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle,
CURLOPT_SSL_CTX_FUNCTION, *fa_sslctx_config_func);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_SSL_CTX_FUNCTION) returned %d (%s)", __func__,
curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_CTX_DATA,
handle);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_SSL_CTX_DATA) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_USE_SSL,
CURLUSESSL_ALL);
if (curlcode != CURLE_OK) {
printf("%s(): curl_easy_setopt(CURLOPT_USE_SSL)
returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER,
insecure ? 0 : 1);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_SSL_VERIFYPEER) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST,
insecure ? 0 : 2);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_SSL_VERIFYHOST) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1);
if (curlcode != CURLE_OK) {
printf("%s(): curl_easy_setopt(CURLOPT_NOSIGNAL)
returned %d (%s)", __func__, curlcode, curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER,
handle->curl_error);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_ERRORBUFFER) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
curl_easy_cleanup(curl_handle);
goto ERROUT;
}
if (fresh_connection) {
fresh_connect = 1L;
cache_timeout_age = 0L;
handle->last_connection_refresh = time(NULL);
handle->force_fresh_connection = false;
printf("%s(): Forcing connection refresh and
clearing DNS cache", __func__);
}
curlcode = curl_easy_setopt(curl_handle, CURLOPT_FRESH_CONNECT,
fresh_connect);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_FRESH_CONNECT) returned %d (%s)", __func__, curlcode,
curl_easy_strerror(curlcode));
/* the rest of the connection has been setup
properly, continue on error */
}
curlcode = curl_easy_setopt(curl_handle,
CURLOPT_DNS_CACHE_TIMEOUT, cache_timeout_age);
if (curlcode != CURLE_OK) {
printf("%s():
curl_easy_setopt(CURLOPT_DNS_CACHE_TIMEOUT) returned %d (%s)", __func__,
curlcode, curl_easy_strerror(curlcode));
/* the rest of the connection has been setup
properly, continue on error */
}
printf("%s(): running curl_easy_perform", __func__);
curlcode = curl_easy_perform(curl_handle);
if (curlcode != CURLE_OK) {
switch (curlcode) {
case CURLE_SSL_CERTPROBLEM:
printf("%s():
received curl error: %s for %s port %d, we will assume that our certificate is
bad, we remove current "
"certificate to obtain a new one via EST", __func__,
curl_easy_strerror(curlcode), url, port);
break;
case CURLE_SSL_CACERT:
printf("%s():
received curl error: %s for %s port %d we need to manually obtain a new CA
certificate", __func__,
curl_easy_strerror(curlcode), url, port);
break;
case CURLE_SSL_CONNECT_ERROR:
if
(strncmp(handle->curl_error, CURL_UNKNOWN_CA_SSL_ERROR,
sizeof(CURL_UNKNOWN_CA_SSL_ERROR) - 1) == 0) {
printf("%s(): curl_easy_perform returned SSL connect error for %s port %d.",
__func__, url, port);
} else {
printf("%s(): curl_easy_perform SSL connect error (%s) for %s port %d",
__func__, handle->curl_error, url, port);
}
break;
case CURLE_COULDNT_RESOLVE_PROXY:
case CURLE_COULDNT_RESOLVE_HOST:
/* When running
from a VM, on wake we sometimes see issues with resolving hostnames, force a
fresh connection on next request */
if
((handle->last_connection_refresh == 0) ||
((time(NULL) - handle->last_connection_refresh) >
MIN_CONNECTION_REFRESH_PERIOD)) {
handle->force_fresh_connection = true;
}
/* fall through */
default:
printf("%s():
curl_easy_perform for %s port %d returned %d (%s) (%s)", __func__, url, port,
curlcode,
curl_easy_strerror(curlcode), handle->curl_error);
break;
}
curl_easy_cleanup(curl_handle);
/*
* Here we differentiate between whether a server
is unreachable
* or another error has occurred such as a
timeouts or an invalid
* response from the server.
*
* We consider the server unreachable if we can't
connect to it,
* we failed to resolve the host/proxy, we've been
* redirected too many times or an SSL connect
error was
* encountered.
*/
if ((curlcode == CURLE_COULDNT_CONNECT) ||
(curlcode ==
CURLE_COULDNT_RESOLVE_HOST) ||
(curlcode ==
CURLE_COULDNT_RESOLVE_PROXY) ||
(curlcode ==
CURLE_TOO_MANY_REDIRECTS) ||
(curlcode ==
CURLE_SSL_CONNECT_ERROR)) {
if (handle->connection_failed_cb) {
handle->connection_failed_cb(send_ts);
}
} else if (handle->connection_reachable_cb) {
handle->connection_reachable_cb();
}
goto ERROUT;
}
printf("%s(): curl_easy_perform returned", __func__);
From: curl-library [mailto:[email protected]] On Behalf Of Ray
Satiro via curl-library
Sent: Thursday, December 08, 2016 4:44 PM
To: [email protected]
Cc: Ray Satiro <[email protected]>
Subject: Re: Access violation in Curl_hash_add
On 12/8/2016 6:27 PM, Jake Fehr (jfehr) wrote:
Our use of Curl is pretty straightforward:
1. Call curl_easy_init()
2. Make (and check the result of) several calls to curl_easy_setopt(),
setting up proxy, url, port, ssl, etc.
3. Call curl_easy_perform()
I can provide the code if needed.
Please provide a self contained example that can be used to reproduce, your
curl_version() and the OS you're using.
-------------------------------------------------------------------
List admin: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html